package firbi.base;

import java.util.HashMap;

import android.app.Instrumentation;
import android.content.Intent;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.KeyEvent;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import firbi.base.com.Bus;
import firbi.base.com.BusStop;
import firbi.base.util.Constants;

public class StopView_Functional_Test extends ActivityInstrumentationTestCase2<StopView> {
	
	private Intent mStartIntent;
	private BusStop mBusStop;
	private StopView mStopView;
	
	public StopView_Functional_Test() {
		super("firbi.base", StopView.class);
	}
	
	@Override
    protected void setUp() throws Exception {
        super.setUp();

        // In setUp, you can create any shared test data, or set up mock components to inject
        // into your Activity.  But do not call startActivity() until the actual test methods.
        mStartIntent = new Intent(Intent.ACTION_MAIN);
    }
	
	
	/**
	 * Test to make sure that all components are not null and stop info is displayed correctly
	 */
	@SmallTest
	public void testUIComponents(){
		mStartIntent.putExtra(Constants.sSTOP_KEY, "0001_35825");
		setActivityIntent(mStartIntent);
		mStopView = this.getActivity();
		while(!mStopView.isThreadReady());
		
		TextView address =(TextView) mStopView.findViewById(R.id.address);
		TextView stopNumber =(TextView) mStopView.findViewById(R.id.stopId);
		ListView list = (ListView) mStopView.getListView();
	
		//check for the view element
		assertNotNull(list);
		assertNotNull(mStopView);
		assertNotNull(stopNumber);
		assertNotNull(address);
		
		//check if the text display properly
		assertEquals("address should be 23rd Ave E", address.getText().toString().trim(), "23rd Ave E & E John St");
		assertEquals("Stop number should be Stop# 35825", stopNumber.getText().toString().trim(), "Stop# 35825");
	}
	
	
	/**
	 * Test to make sure that the list display data from currentArrival properly
	 */
	@SmallTest
	public void testUnOrderedList(){
		mStartIntent.putExtra(Constants.sSTOP_KEY, "0001_35825");
		setActivityIntent(mStartIntent);
		mStopView = this.getActivity();
		while(!mStopView.isThreadReady());
		ListView list = (ListView) mStopView.getListView();
		ListAdapter listAdapter = list.getAdapter();
		compareListAdapterWithCurrentArrivals(mStopView,mStopView.getCurrentArrivals(),listAdapter);
	}
	
	/**
	 * Helper method used to all items in listAdapter against currentArrivals
	 * @param mStopView
	 * @param currentArrivals
	 * @param listAdapter
	 */
	private void compareListAdapterWithCurrentArrivals(StopView mStopView ,Bus[] currentArrivals, ListAdapter listAdapter){
		if (currentArrivals==null) {
			assertEquals(0, listAdapter.getCount());
			return;
		}
		for(int i=0;i< currentArrivals.length;i++){
			Bus tempBus = currentArrivals[i];
			HashMap<String,String> item = (HashMap<String,String>) listAdapter.getItem(i);
			assertEquals(tempBus.getRoute().getRouteNumber(), item.get("routeColumn"));
			assertEquals(tempBus.getDestination(), item.get("destinationColumnFirstRow"));
			assertEquals(mStopView.predictedTimeandStatus(tempBus), item.get("destinationColumnSecondRow"));
			assertEquals(mStopView.calculateArrivalStatus(tempBus), item.get("minutesColumn"));
		}
	}
	
	/**
	 * Test to make sure that the list display data from currentArrival properly
	 */
	@SmallTest
	public void testOrderedList(){
		mStartIntent.putExtra(Constants.sSTOP_KEY, "0001_35825");
		mStartIntent.putExtra(Constants.sROUTE_KEY, "0001_43");
		setActivityIntent(mStartIntent);
		StopView mStopView = this.getActivity();
		while(!mStopView.isThreadReady());
		ListView list = (ListView) mStopView.getListView();
		ListAdapter listAdapter = list.getAdapter();
		isThisRouteAtTheTopOfTheList("43", listAdapter); //check to see all 43 are pushed to top of the list
	}
	
	/**
	 * Helper method to check if a route number is sorted to the top of the list
	 * @param wantedRoute
	 * @param listAdapter
	 */
	private void isThisRouteAtTheTopOfTheList(String wantedRoute,ListAdapter listAdapter ){
		boolean foundOtherRoute=false;
		if (listAdapter.getCount() > 0){ // we have some result to be tested
			HashMap<String,String> item = (HashMap<String,String>) listAdapter.getItem(0);
			if (item.get("routeColumn").equals(wantedRoute)){ //there is at least one wantedRoute
				for(int i=1;i< listAdapter.getCount();i++){
					item = (HashMap<String,String>) listAdapter.getItem(i);
					if (!item.get("routeColumn").equals(wantedRoute)){
						foundOtherRoute = true;
					}else{
						//if other route listed before wantedRoute, the test should fail
						if (foundOtherRoute) assertFalse("found wantedRoute after other route",true); 
					}
				}
			}else{//check to make sure that wantedRoute is not in the list at all
				for(int i=1;i< listAdapter.getCount();i++){
					assertFalse("If wantedRoute is not the first item, wantedRoute should not appear anywhere",item.get("routeColumn").equals(wantedRoute));
				}
			}
		}
	}
	
	/**
	 * Test to make sure that menu responds properly
	 * 1.open Favorites when favorites is clicked
	 * 2.open Search when "search in map mode" or "search in list mode" is clicked
	 */
	@SmallTest
	public void testMenuClick(){
		Instrumentation.ActivityMonitor mFavoriteMonitor = new Instrumentation.ActivityMonitor("firbi.base.Favorites", null, true);
		Instrumentation.ActivityMonitor mSearchMonitor = new Instrumentation.ActivityMonitor("firbi.base.Search", null, true);
		this.getInstrumentation().addMonitor(mSearchMonitor);
		this.getInstrumentation().addMonitor(mFavoriteMonitor);
		
		mStartIntent.putExtra(Constants.sSTOP_KEY, "0001_35825");
		mStartIntent.putExtra(Constants.sROUTE_KEY, "0001_43");
		mStartIntent.putExtra("isMapView", true);
		setActivityIntent(mStartIntent);
		mStopView = this.getActivity();
		while(!mStopView.isThreadReady());
		wait(1);
		
		assertEquals("Favoriate has never been called",0, mFavoriteMonitor.getHits());
		sendKeys(KeyEvent.KEYCODE_MENU);
		sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
		sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
		sendKeys(KeyEvent.KEYCODE_ENTER);
		assertEquals("Favoriates has been been called once",1, mFavoriteMonitor.getHits());
		
		assertEquals("Search has never been called",0, mSearchMonitor.getHits());
		sendKeys(KeyEvent.KEYCODE_MENU);
		sendKeys(KeyEvent.KEYCODE_DPAD_UP);
		sendKeys(KeyEvent.KEYCODE_ENTER);
		assertEquals("Search has been been called once",1, mSearchMonitor.getHits());
		
		mStartIntent.putExtra("isMapView", false);
		setActivityIntent(mStartIntent);
		mStopView = this.getActivity();
		while(!mStopView.isThreadReady());
		wait(1);
		assertEquals("Search has been been called once",1, mSearchMonitor.getHits());
		sendKeys(KeyEvent.KEYCODE_MENU);
		sendKeys(KeyEvent.KEYCODE_DPAD_UP);
		sendKeys(KeyEvent.KEYCODE_ENTER);
		assertEquals("Search has been been called for second time with diferrent",2, mSearchMonitor.getHits());
	}
	
	/**
	 * Test to make sure when there is data in the list, a click on list item should call RouteView
	 */
	@SmallTest
	public void testListClick(){
		Instrumentation.ActivityMonitor mRouteViewMonitor = new Instrumentation.ActivityMonitor("firbi.base.RouteView", null, true);
		this.getInstrumentation().addMonitor(mRouteViewMonitor);
		mStartIntent.putExtra(Constants.sROUTE_KEY, "0001_43");
		mStartIntent.putExtra(Constants.sSTOP_KEY, "0001_35825");
		setActivityIntent(mStartIntent);
		mStopView = this.getActivity();
		while(!mStopView.isThreadReady());
		wait(1);
		ListView list = (ListView) mStopView.getListView();
		ListAdapter listAdapter = list.getAdapter();
		if (listAdapter.getCount()>0){//we can test since there is something in the list
			mStopView.onListItemClick(list, mStopView.getCurrentFocus(), 0, 0);
			assertEquals(1, mRouteViewMonitor.getHits());
		}
	}
	
	
	/**
	 * helper method to use thread sleep
	 * @param sec
	 */
	private void wait(int sec){
		try {
			Thread.sleep(1000*sec);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
